// 交费核实管理

package student

import (
	"api/common"
	"api/common/logger"
	"api/common/orm"
	"api/common/web"
	"api/models"
	"net/http"
	"strconv"
	"strings"
	"time"
)

// @TagName 交费核实管理
// @Controller CountController
type CountController struct{}

// @Title 已交费列表数据
// @Route /count/list --> List
// @Method post
func (this *CountController) List(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	model := &models.Info{}
	fields := "id, `name`, sex, id_card_num, phone, phone_backup," +
		" special_id, lodging, fee, `status`, type"
	where := "(`status`=2 or `status`=5)"
	order := "`status`, add_time"
	web.JsonCallBakFilter(w, inputJson, model, fields, where, order)
}

// @Title 已交费列表数据(返回所有字段)
// @Route /count/listAll --> ListAll
// @Method post
func (this *CountController) ListAll(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	ids := inputJson["ids"]
	model := &models.Info{}
	where := "(`status`=2 or `status`=5)"
	if ids != nil && ids != "" {
		where += " and id in (" + common.ToStr(ids) + ")"
	}
	order := "`status`, add_time"
	page, msg := web.JsonRootWithInputFilter(inputJson, model, "", where, order)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	// 对审核通过的学生记录，附加审核员姓名
	sql := "select id, `name` from basic_user"
	arr := []models.User{}
	conn := orm.NewOrm()
	_, err := conn.Raw(sql).QueryRows(&arr)
	if err != nil {
		logger.Error("查询id与name的映射关系发生错误：", err.Error())
		web.ServeJSON(w, web.JsonMsg{false, err.Error(), 1})
		return
	}

	obj := map[uint32]string{}
	for _, item := range arr {
		obj[item.Id] = item.Name
	}

	for i := 0; i < len(page.Root); i += 1 {
		item := page.Root[i]
		id, _ := strconv.Atoi(item["auditAdmin"].(string))
		page.Root[i]["auditAdminName"] = obj[uint32(id)]
	}

	web.ServeJSON(w, page)
}

// @Title 交费核实通过
// @Route /count/allow --> Allow
// @Param {"userId":1,"token":"a","studentId":0,"fee":1000.0}
// @Method post
func (this *CountController) Allow(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	userId := inputJson["userId"]
	studentId := inputJson["studentId"]
	fee := inputJson["fee"]
	feeValue := float32(fee.(float64))
	if studentId == nil {
		web.ServeJSON(w, web.JsonMsg{false, "学生id不能为空", 1})
		return
	}
	if fee == nil {
		web.ServeJSON(w, web.JsonMsg{false, "交费金额不能为空", 1})
		return
	}
	if feeValue <= 0 {
		web.ServeJSON(w, web.JsonMsg{false, "交费金额必须大于零", 1})
		return
	}

	user := &models.Info{}
	sql := "select * from student_info where id=?"
	conn := orm.NewOrm()
	err := conn.Raw(sql, studentId).QueryRow(user)
	if err != nil {
		if strings.Index(err.Error(), "no row found") == -1 {
			logger.Info("验证用户信息发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "验证用户信息发生错误" + err.Error(), 1})
			return
		}

		web.ServeJSON(w, web.JsonMsg{false, "学生记录不存在", 1})
		return
	}
	if user.Status != 2 {
		//状态: 0已注册待报名, 1已报名待审核, 2审核通过待交费, 3审核被拒, 4已交费待核实, 5已核实待分配, 6已分配
		web.ServeJSON(w, web.JsonMsg{false, "用户状态不正确", 1})
		return
	}

	if user.WeixinId != "" {
		// 检查"操作记录"里是否有依据(是否有前一状态的记录)
		count := 0
		sql = "select count(1) from student_operate_record where" +
			" student_id=? and add_time<now() and" +
			" `status`=2 and admin_id>0 and remark=''" +
			//" `status`=4 and admin_id=0 and remark!=''" +
			" order by add_time desc"
		err = conn.Raw(sql, studentId).QueryRow(&count)
		if err != nil {
			logger.Error("查询操作记录数量发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询操作记录数量发生错误" + err.Error(), 1})
			return
		}
		if count == 0 {
			web.ServeJSON(w, web.JsonMsg{false, "“操作记录”表里没有前一状态的记录", 1})
			return
		}
	}

	user.Status = 5 // 更新用户状态为: 交费成功
	user.Fee = feeValue
	user.FeeTime = time.Now()
	_ = conn.Begin()
	_, err = conn.Update(user)
	if err != nil {
		_ = conn.Rollback()
		logger.Error("更新记录发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "更新记录发生错误" + err.Error(), 1})
		return
	}

	rec := &models.OperateRecord{
		StudentId: user.Id,
		AdminId:   uint32(userId.(float64)),
		Status:    5, // 交费成功
		Remark:    common.ToStr(fee),
	}
	_, err = conn.Insert(rec)
	if err != nil {
		_ = conn.Rollback()
		logger.Error("操作记录入库发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "操作记录入库发生错误" + err.Error(), 1})
		return
	}
	_ = conn.Commit()

	if user.WeixinId != "" {
		// 根据专业id查询专业名称
		sql = "select `name` from basic_special where id=?"
		specialName := ""
		err = conn.Raw(sql, user.SpecialId).QueryRow(&specialName)
		if err != nil {
			logger.Error("查询专业名称发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询专业名称发生错误" + err.Error(), 1})
			return
		}

		// 根据报考类别数值获取报考类别名称
		mappingType := map[uint32]string{}
		mappingType[1] = "职教高考"
		mappingType[2] = "职业中专"
		mappingType[3] = "职业中专(3+2)"
		mappingType[4] = "技工"
		mappingType[5] = "技工(3+2)"
		typeName := mappingType[user.Type]

		// 及时通知微信用户交费核实的结果
		sendData := []common.Item{}
		item := common.Item{
			Field: "thing1",
			Value: user.Name,
		}
		sendData = append(sendData, item)

		item = common.Item{
			Field: "character_string2",
			Value: user.IdCardNum,
		}
		sendData = append(sendData, item)

		item = common.Item{
			Field: "thing5", // 报名专业
			Value: specialName + " - " + typeName,
		}
		sendData = append(sendData, item)

		item = common.Item{
			Field: "phrase3",
			Value: "交费成功",
		}
		sendData = append(sendData, item)

		errMsg := common.SendMsg(
			user.WeixinId,
			common.Config.WX.MessageTemplate.Pay,
			sendData,
		)
		if errMsg != "" {
			web.ServeJSON(w, web.JsonMsg{true, "交费核实操作成功，但是" + errMsg, 2})
			return
		}
	}

	web.ServeJSON(w, web.JsonMsg{true, "交费核实操作成功", 0})
}

// @Title 删除学生报名信息
// @Route /count/delete --> Delete
// @Method post
func (this *CountController) Delete(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	web.DeleteCallBak(w, r, &models.Info{})
}

// @Title 交费核实撤销
// @Route /count/undo --> Undo
// @Param {"userId":1,"token":"a","studentId":0}
// @Method post
func (this *CountController) Undo(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	userId := inputJson["userId"]
	studentId := inputJson["studentId"]
	if studentId == nil {
		web.ServeJSON(w, web.JsonMsg{false, "学生id不能为空", 1})
		return
	}

	user := &models.Info{}
	sql := "select * from student_info where id=?"
	conn := orm.NewOrm()
	err := conn.Raw(sql, studentId).QueryRow(user)
	if err != nil {
		if strings.Index(err.Error(), "no row found") == -1 {
			logger.Info("验证用户信息发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "验证用户信息发生错误" + err.Error(), 1})
			return
		}

		web.ServeJSON(w, web.JsonMsg{false, "学生记录不存在", 1})
		return
	}
	if user.Status != 5 {
		//状态: 0已注册待报名, 1已报名待审核, 2审核通过待交费, 3审核被拒, 4已交费待核实, 5已核实待分配, 6已分配
		web.ServeJSON(w, web.JsonMsg{false, "用户状态不正确", 1})
		return
	}

	if user.WeixinId != "" {
		// 检查"操作记录"里是否有依据(是否有前一状态的记录)
		count := 0
		sql = "select count(1) from student_operate_record where" +
			" student_id=? and add_time<now() and" +
			" `status`=5 and admin_id>0 and remark!=''" +
			" order by add_time desc"
		err = conn.Raw(sql, studentId).QueryRow(&count)
		if err != nil {
			logger.Error("查询操作记录数量发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询操作记录数量发生错误" + err.Error(), 1})
			return
		}
		if count == 0 {
			web.ServeJSON(w, web.JsonMsg{false, "“操作记录”表里没有前一状态的记录", 1})
			return
		}
	}

	user.Status = 2 // 更新用户状态为: 审核通过待交费
	user.Fee = 0
	_ = conn.Begin()
	_, err = conn.Update(user)
	if err != nil {
		_ = conn.Rollback()
		logger.Error("更新记录发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "更新记录发生错误" + err.Error(), 1})
		return
	}

	rec := &models.OperateRecord{
		StudentId: user.Id,
		AdminId:   uint32(userId.(float64)),
		Status:    2, // 审核通过待交费
		Remark:    "交费核实撤销",
	}
	_, err = conn.Insert(rec)
	if err != nil {
		_ = conn.Rollback()
		logger.Error("操作记录入库发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "操作记录入库发生错误" + err.Error(), 1})
		return
	}
	_ = conn.Commit()

	web.ServeJSON(w, web.JsonMsg{true, "交费核实撤销成功", 0})
}
